#!/bin/bash
#Time: 2022-04-14 23:56:59
#Desc: 对文件进行签名，目前主要是对ko签名

g_sign_token="z2f8rCL-"
g_sign_server="9.134.235.45"
g_public_key_md5="0ac1e2cea65f0488a4c2e38135ee4471"

function upload_file() {
    local result
    local errno
    result=$(curl -s -F "token=${g_sign_token}" -F "action=file_upload" -F "namespace=$2" -F "upload-file=@$1" \
        http://${g_sign_server}/cgi-bin/sign_svr/cgi-bin/file_list.cgi)
    errno=$(echo $result | awk '{print $4}')
    if [ "$errno" == "0," ]; then
        echo "upload $1 succeed"
        return 0
    else
        echo "upload $1 failed"
        echo "$result"
        return 1
    fi
}

function sign_file() {
    local result
    local errno
    result=$(curl -s -F "token=${g_sign_token}" -F "action=file_sign" -F "namespace=$3" -F "file_name=$1" \
        -F "oper_reson='sign'" -F "key_md5=$2" http://${g_sign_server}/cgi-bin/sign_svr/cgi-bin/file_list.cgi)
    errno=$(echo $result | awk '{print $4}')
    if [ "$errno" == "0," ]; then
        echo "sign $1 succeed"
        return 0
    else
        echo "sign $1 failed"
        echo "$result"
        return 1
    fi
}

function download_file() {
    curl -s -F "token=${g_sign_token}" -F "action=file_download" -F "namespace=$2" -F "file_name=$1" -F "type=signed" \
        http://${g_sign_server}/cgi-bin/sign_svr/cgi-bin/file_list.cgi >$3
    is_file_ok $3
    if [ $? -eq 0 ]; then
        echo "download $3 ok"
        return 0
    else
        echo "dowload $3 failed"
        cat "$3"
        return 1
    fi
}

function verify_module() {
    local sig
    sig="$(tail -c 32 "$1" | strings)"
    if echo "$sig" | grep "~Module signature appended~"; then
        echo "verify module $1 ok"
        return 0
    else
        echo "verify module $1 failed"
        return 1
    fi
}

function is_file_ok() {
    local first_char
    first_char=$(head -c 1 $1)
    if [ "$first_char" == "{" ]; then
        return 1
    fi
    return 0
}

function get_public_key() {
    curl -s -F "token=${g_sign_token}" -F "action=get_default_key_file" \
        http://${g_sign_server}/cgi-bin/sign_svr/cgi-bin/file_list.cgi >$1 || return 1
    is_file_ok $1
    if [ $? -eq 0 ]; then
        g_public_key_md5=$(md5sum $1 | awk '{print $1}')
        echo "get_public_key ok, md5 is: $g_public_key_md5"
        return 0
    else
        echo "get_public_key failed"
        return 1
    fi
}

sign_module() {
    # params: unsigned_name signed_name
    local unsigned_name="$1"
    local file_name=$(basename $1)
    local dir_name=$(dirname "$1")
    local signed_name="$2"
    upload_file "${unsigned_name}" "${dir_name}"
    if [ $? -ne 0 ]; then
        return 1
    fi
    sign_file "${file_name}" "${g_public_key_md5}" "${dir_name}"
    if [ $? -ne 0 ]; then
        return 1
    fi
    download_file "${file_name}" "${dir_name}" "${signed_name}"
    if [ $? -ne 0 ]; then
        return 1
    fi
    verify_module "${signed_name}"
    if [ $? -ne 0 ]; then
        return 1
    fi
    return 0
}

file_size() {
    stat --format="%s" "$1"
}

main_sign_ko() {
    local sign_tmpdir="$TST_TS_SYSDIR/sign.tmpdir"

    if uname -r | grep "^6\.6\."; then
        echo "tk5 sign always"
    elif ! uname -r | grep -i "tlinux"; then
        echo "the ko file of this system does not need to be signed"
        return 0
    fi

    rm -rf "$sign_tmpdir"
    mkdir -p "$sign_tmpdir/signed"

    for file in "$@"; do
        if ! echo "$file" | grep "^/"; then
            file="$(realpath "$TST_TS_ORI_CWD/$file")"
        fi
        if verify_module "$file" >/dev/null 2>&1; then
            continue
        fi
        if [ ! -f "$sign_tmpdir/signing_key.pub" ]; then
            get_public_key "$sign_tmpdir/signing_key.pub" || return 1
        fi
        target_file="$sign_tmpdir/signed/$(basename "$file")"
        original_size=$(file_size "${file}")
        echo "signing ${file}"
        sign_module "${file}" "${target_file}" || return 1
        signed_size=$(file_size "${target_file}")
        echo "file size: ${original_size} -> ${signed_size}"
        mv -v "$target_file" "$file"
    done
}
